package xtreamclient.api

import com.fasterxml.jackson.dataformat.xml.XmlMapper
import com.fasterxml.jackson.module.kotlin.KotlinModule
import com.google.gson.reflect.TypeToken
import okhttp3.*
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.jackson.JacksonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Query
import xtreamclient.ServerProperties
import java.lang.Exception
import java.lang.reflect.Type


public interface XtreamService {
    @GET("player_api.php") @Json
    suspend fun authenticate(): PlayerApi

    @GET("player_api.php?action=get_live_categories") @Json
    suspend fun getLiveStreamCategories(): List<MediaCategory>

    @GET("player_api.php?action=get_vod_categories") @Json
    suspend fun getVodCategories(): List<MediaCategory>


    @GET("player_api.php?action=get_live_streams") @Json
    suspend fun getAllStreams(): List<LiveStream>

    @GET("player_api.php?action=get_live_streams") @Json
    suspend fun getStreams(@Query("category_id")categoryId: String): List<LiveStream>

    @GET("xmltv.php") @Xml
    suspend fun getCompleteEPG():TV


    @GET("player_api.php?action=get_vod_categories") @Json
    suspend fun getVODCategories(): List<MediaCategory>

    @GET("player_api.php?action=get_vod_streams") @Json
    suspend fun getVODStreams(@Query("category_id")categoryId: String):List<Movie>

    @GET("player_api.php?action=get_series") @Json
    suspend fun getSeries(): List<Series>

    @GET("player_api.php?action=get_series_info") @Json
    suspend fun getSeriesOverview(@Query("series_id")categoryId: String):SeriesOverview


}

object Xtream {
    fun loadService(properties: ServerProperties): XtreamService {

        val okHttpClient = OkHttpClient()
            .newBuilder()
            .addInterceptor(XtreamAuthInterceptor(properties))

            .build()


        val retrofit = Retrofit.Builder()
            .baseUrl(properties.hostname + ":" + properties.port + "/")
            .client(okHttpClient)
            .addConverterFactory(XmlOrJsonConverterFactory())
            .build()
        return retrofit.create(XtreamService::class.java)
    }
}

class XtreamAuthInterceptor(val properties: ServerProperties) : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val originalRequest = chain.request()

        val url = originalRequest.url.newBuilder()
            .addQueryParameter("username", properties.username)
            .addQueryParameter("password", properties.password)
            .build()
        println("Injecting passwords, url is now: $url")
        val request = chain.request().newBuilder().url(url).build()
        return chain.proceed(request)
    }

}


internal annotation class Xml

internal annotation class Json

internal class XmlOrJsonConverterFactory : Converter.Factory() {
    val xmlMapper = XmlMapper().registerModule(KotlinModule())
    val jsonConverter = GsonConverterFactory.create()
    val xmlConverter = JacksonConverterFactory.create(xmlMapper)


    override fun responseBodyConverter(
        type: Type,
        annotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<ResponseBody, *>? {
        for (annotation in annotations) {
            if (annotation.annotationClass == Xml::class){
                return xmlConverter.responseBodyConverter(type,annotations,retrofit)
            }
        }
        return jsonConverter.responseBodyConverter(type,annotations,retrofit)
    }

    override fun requestBodyConverter(
        type: Type,
        parameterAnnotations: Array<Annotation>,
        methodAnnotations: Array<Annotation>,
        retrofit: Retrofit
    ): Converter<*, RequestBody>? {
        return jsonConverter.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit)
    }
}